<template>
  <div class="avatar-uploader">
    <el-upload :before-upload="beforeUpload" :http-request="customUpload" :on-error="handleError" :accept="'image/*'">
      <!-- 自定义上传框 -->
      <slot name="trigger"></slot>
      <template v-if="!$slots.trigger">
        <div class="avatar-upload avatar-placeholder">
          <img v-if="avatarUrl" :src="avatarUrl" class="avatar" />
          <template v-else>
            <el-icon><Plus /></el-icon>
            <div class="upload-text">点击上传头像</div>
          </template>
        </div>
      </template>

      <!-- 上传框下方的提示说明文字 -->
      <template v-if="tip" #tip>
        <div class="el-upload__tip">{{ tipText }}</div>
      </template>
    </el-upload>
  </div>
</template>

<script setup lang="ts" name="UploadImage">
import { ElMessage } from "element-plus";
import * as Api from "@/api/modules/media";

interface Props {
  modelValue?: string; // 图片地址
  isPublic?: number; // 0 私有 1 公开
  fileSizeLimit?: number; // 单位 MB
  tip?: string; // 提示文字
  disabled?: boolean; // 是否禁用
}

import { getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();

const props = withDefaults(defineProps<Props>(), {
  modelValue: "",
  isPublic: 1,
  fileSizeLimit: 2,
  disabled: false
});
const emit = defineEmits(["update:modelValue", "uploadSuccess"]);

const avatarUrl = ref(props.modelValue);
watch(
  () => props.modelValue,
  val => (avatarUrl.value = val)
);

const beforeUpload = (file: File) => {
  const isImage = file.type.startsWith("image/");
  const isLtSize = file.size / 1024 / 1024 < props.fileSizeLimit;
  if (!isImage) {
    ElMessage.error(proxy.$safeT("msg.onlyImage"));
    return false;
  }
  if (!isLtSize) {
    ElMessage.error(proxy.$safeT("msg.fileSizeLimit") + isLtSize + "MB");
    return false;
  }
  return true;
};

const customUpload = async ({ file, onSuccess, onError, onProgress }: any) => {
  const formData = new FormData();
  formData.append("file", file);
  formData.append("isPublic", String(props.isPublic));
  try {
    const res = await Api.addMedia(formData, onProgress);
    const url = res.data.media.fileUrl;
    avatarUrl.value = url;
    emit("update:modelValue", url);
    emit("uploadSuccess", url);
    onSuccess(res);
  } catch (err) {
    onError(err);
  }
};

const handleError = () => {
  ElMessage.error(proxy.$safeT("msg.uploadedError"));
};
const tipText = computed(() => props.tip || `可上传图${props.fileSizeLimit}MB以内）`);
</script>

<style scoped lang="scss">
.card {
  user-select: none;
}
.avatar-uploader {
  display: inline-block;
}
.avatar-upload {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 128px;
  height: 128px;
  overflow: hidden;
  cursor: pointer;
  border: 1px dashed #dcdfe6;
  border-radius: 50%;
}
.avatar-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: var(--el-text-color-secondary);
}
.upload-text {
  margin-top: 4px;
  font-size: 12px;
}
.avatar {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.el-upload__tip {
  text-align: center;
}
</style>
